/**
 * Copyright (C) 2010, 2011 Neofonie GmbH
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package eu.dicodeproject.blogimport.parser;

import java.io.Serializable;
import java.util.Map;
import java.util.Set;

/**
 * The Class BlogDocument represents a blog entry. 
 * The bean consists of common used attributes accessible via direct getter
 * methods and a maps, that can hold the complete content of a
 * document. 
 * 
 * Currently three ways of accessing data are supported:
 * <ul>
 * <li>use the getContentMapKeys() method and traverse through the map</li>
 * <li>use the ContentMapFields enumeration WITH the toString methods as keys,
 * e.g. ContentMapFields.TITLE.toString()</li>
 * <li>know the xpath of the node's content you want to access and transform it
 * into the format we use internally, e.g.
 * /Document/Content/Blog/Author must be transformed to
 * Document_Content_Blog_Author as the key</li>
 * </ul>
 * 
 * 
 */

public class BlogDocument implements Serializable {

  private static final long serialVersionUID = 157575098436052L;

  private static final String SEPARATOR = "#";

  // TODO: Check if we want to have a map of Type <String, Object> as before
  // because otherwise we cannot return objects via XPath keys.
  /** Generic map for /Document/Content nodes. */
  private Map<String, String> contentMap;

  /**
   * C'tor that initializes the object with an InitDocument that was created
   * inside the parser to hide setter methods.
   * 
   * @param inDoc
   *          the initial content
   */
  public BlogDocument(final InitDocument inDoc) {
    this.contentMap = inDoc.getContentMap();
  }

  /**
   * @return the blog title
   */
  public String getBlogtitle() {
    return this.contentMap.get(ContentMapFields.BLOGTITLE.toString());
  }

  /**
   * @return the language
   */
  public String getLanguage() {
    return this.contentMap.get(ContentMapFields.LANGUAGE.toString());
  }

  /**
   * @return the title
   */
  public String getTitle() {
    return this.contentMap.get(ContentMapFields.TITLE.toString());
  }

  /**
   * @return the url
   */
  public String getUrl() {
    return this.contentMap.get(ContentMapFields.URL.toString());

  }

  /**
   * @return the publicationTime
   */
  public long getPublishTimestamp() {
    String val = this.contentMap.get(ContentMapFields.PUBLISHTIMESTAMP.toString());
    String returnValue = "0";
    if (val != null) {
      returnValue = val.toString();
    }
    return Long.parseLong(returnValue);
  }

  /**
   * @return the text
   */
  public String getBody() {
    return this.contentMap.get(ContentMapFields.BODY.toString());
  }

  /**
   * @return the author
   */
  public String getAuthor() {
    return this.contentMap.get(ContentMapFields.AUTHOR.toString());
  }

  /**
   * @return automatic tags
   */
  public String getAutotags() {
    StringBuilder sb = new StringBuilder();
    for (String key : getContentMapKeys()) {
      if (key.startsWith(ContentMapFields.AUTOTAGS.toString())) {
        sb.append(this.contentMap.get(key) + SEPARATOR);
      }
    }
    return clean(sb.toString());
  }

  /**
   * @return tags
   */
  public String getTags() {
    StringBuilder sb = new StringBuilder();
    for (String key : getContentMapKeys()) {
      if (key.startsWith(ContentMapFields.TAGS.toString())) {
        sb.append(this.contentMap.get(key) + SEPARATOR);
      }
    }
    return clean(sb.toString());
  }

  /**
   * @return catgeories
   */
  public String getCategories() {
    StringBuilder sb = new StringBuilder();
    for (String key : getContentMapKeys()) {
      if (key.startsWith(ContentMapFields.CATEGORIES.toString())) {
        sb.append(this.contentMap.get(key) + SEPARATOR);
      }
    }
    return clean(sb.toString());
  }

  /**
   * Removes the trailing separator from composite fields
   * 
   * @param str
   * @return
   */
  private String clean(String str) {
    if (str.length() > SEPARATOR.length()) {
      return str.substring(0, str.length() - SEPARATOR.length());
    } else {
      return null;
    }
  }

  /**
   * @return the rawXML
   */
  @Deprecated
  public String getRawXML() {
    return null;
  }

  /**
   * Gets all keys of the content map.
   * 
   * @return set of keys.
   */
  public Set<String> getContentMapKeys() {
    return this.contentMap.keySet();
  }

  /**
   * HashCode implementation that is based on the url combined with the
   * semantical equal urlhash of a {@link BlogDocument}.
   * 
   * @see java.lang.Object#hashCode()
   */
  @Override
  public int hashCode() {
    final int prime = 13;
    int result = 1;
    result = prime * result + ((this.getUrl() == null) ? 0 : this.getUrl().hashCode());
    return result;
  }

  /**
   * Equals implementation that is based on the url of a {@link BlogDocument}.
   * 
   * @see java.lang.Object#equals(java.lang.Object)
   */
  @Override
  public boolean equals(Object obj) {
    if (this == obj) {
      return true;
    }
    if (obj == null) {
      return false;
    }
    if (getClass() != obj.getClass()) {
      return false;
    }
    BlogDocument other = (BlogDocument) obj;
    if (this.getUrl() == null) {
      if (other.getUrl() != null) {
        return false;
      }
    } else if (!this.getUrl().equals(other.getUrl())) {
      return false;
    }
    return true;
  }

  /**
   * @see java.lang.Object#toString()
   */
  @Override
  public String toString() {
    return "BlogDocument [url=" + this.getUrl() + ", title=" + this.getTitle() + ", publicationTime="
        + this.getPublishTimestamp() + ", language=" + this.getLanguage() + "]";
  }

}
